package com.faxsun.api.endpoint.account;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import com.faxsun.api.wrapper.address.CustomerAddressWrapper;
import com.faxsun.api.wrapper.customer.CustomerWrapper;
import com.faxsun.api.wrapper.customer.MergeCustomerWrapper;
import com.faxsun.api.wrapper.result.ResultWrapper;
import com.faxsun.captcha.service.FSCaptchaService;
import com.faxsun.captcha.service.FSDigitalCaptchaServiceImpl;
import com.faxsun.controller.account.LoginController;
import com.faxsun.controller.uc.entity.CHANNEL;
import com.faxsun.controller.uc.entity.ThirdPartyLoginServer;
import com.faxsun.profile.core.domain.FSAssistant;
import com.faxsun.profile.core.domain.FSCustomer;
import com.faxsun.profile.core.domain.FSThirdPartyCustomer;
import com.faxsun.profile.core.exception.AccountBindedThirdAccountException;
import com.faxsun.profile.core.exception.ThirdAccountBindToMultipleAccountException;
import com.faxsun.profile.core.exception.ThirdAccountBindedException;
import com.faxsun.profile.core.service.FSAssistantService;
import com.faxsun.profile.core.service.FSCustomerService;
import com.faxsun.profile.core.service.FSThirdPartyCustomerService;

import org.apache.commons.lang.StringUtils;
import org.broadleafcommerce.common.exception.ServiceException;
import org.broadleafcommerce.common.security.util.PasswordChange;
import org.broadleafcommerce.common.security.util.PasswordReset;
import org.broadleafcommerce.core.order.domain.Order;
import org.broadleafcommerce.core.order.service.OrderService;
import org.broadleafcommerce.core.order.service.call.OrderItemRequestDTO;
import org.broadleafcommerce.core.order.service.exception.AddToCartException;
import org.broadleafcommerce.core.pricing.service.exception.PricingException;
import org.broadleafcommerce.core.web.api.BroadleafWebServicesException;
import org.broadleafcommerce.core.web.order.CartState;
import org.broadleafcommerce.profile.core.domain.Customer;
import org.broadleafcommerce.profile.web.core.service.login.LoginService;
import org.broadleafcommerce.profile.core.domain.Address;
import org.broadleafcommerce.profile.core.domain.Country;
import org.broadleafcommerce.profile.core.domain.CustomerAddress;
import org.broadleafcommerce.profile.core.domain.Phone;
import org.broadleafcommerce.profile.core.domain.State;
import org.broadleafcommerce.profile.core.service.AddressService;
import org.broadleafcommerce.profile.core.service.CountryService;
import org.broadleafcommerce.profile.core.service.CustomerAddressService;
import org.broadleafcommerce.profile.core.service.CustomerService;
import org.broadleafcommerce.profile.core.service.PhoneService;
import org.broadleafcommerce.profile.core.service.StateService;
import org.broadleafcommerce.profile.web.core.CustomerState;
import org.springframework.context.annotation.Scope;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import javax.ws.rs.core.MediaType;

@Component
@Scope("singleton")
@Path("/customer/")
@Produces(value = { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Consumes(value = { MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public class CustomerEndpoint extends org.broadleafcommerce.core.web.api.endpoint.customer.CustomerEndpoint {
	public static final String USERNAME_EXISTED = "org.broadleafcommerce.core.web.api.BroadleafWebServicesException.usernameExisted";
	public static final String USERNAME_NOT_EXISTED = "org.broadleafcommerce.core.web.api.BroadleafWebServicesException.usernameNotExisted";
	public static final String PASSWORD_ERROR = "org.broadleafcommerce.core.web.api.BroadleafWebServicesException.passwordError";
	public static final String CURRENT_PASSWORD_ERROR = "org.broadleafcommerce.core.web.api.BroadleafWebServicesException.currentPasswordError";
	public static final String SEND_VARIFY_ERROR = "org.broadleafcommerce.core.web.api.BroadleafWebServicesException.sendVarifyError";
	public static final String VARIFY_ERROR = "org.broadleafcommerce.core.web.api.BroadleafWebServicesException.varifyError";
	public static final String UNKNOWN_ERROR = "org.broadleafcommerce.core.web.api.BroadleafWebServicesException.unknownError";
	public static final String ADDRESS_NOT_FOUND = "org.broadleafcommerce.core.web.api.BroadleafWebServicesException.addressNotFound";
	public static final String ADDRESS_IN_ACTIVE_CART = "org.broadleafcommerce.core.web.api.BroadleafWebServicesException.addressInActiveCart";
	public static final String VERIFY_CODE_ERROR = "org.broadleafcommerce.core.web.api.BroadleafWebServicesException.verifyCodeError";
	public static final String SEND_VARIFY_SUCCESS = "org.broadleafcommerce.core.web.api.BroadleafWebServicesException.sendVarifySuccess";

	public static final String HOST = "https://www.faxsun.com/";
	public static final String URI_POSTFIX = "/checkout/pre?code=";

	@Resource(name = "blLoginService")
	LoginService blLoginService;
	protected FSCaptchaService captchaService = FSDigitalCaptchaServiceImpl.getSingleInstance();

	@Resource(name = "blCustomerAddressService")
	CustomerAddressService blCustomerAddressService;

	@Resource(name = "blAddressService")
	AddressService blAddressService;

	@Resource(name = "blPhoneService")
	PhoneService blPhoneService;

	@Resource(name = "blStateService")
	StateService blStateService;

	@Resource(name = "blCountryService")
	CountryService blCountryService;

	@Resource(name = "blCustomerService")
	CustomerService customerService;

	@Resource(name = "blThirdPartyCustomerService")
	FSThirdPartyCustomerService fscustomer3thService;

	@Resource(name = "fsThirdPartyService")
	ThirdPartyLoginServer loginServer3th;

	@Resource(name = "blAssistantService")
	FSAssistantService assistantService;

	@Resource(name = "blOrderService")
	protected OrderService orderService;

	@Resource(name = "fsThirdPartyService")
	ThirdPartyLoginServer thirdPartyLoginServer;

	@GET
	public CustomerWrapper findCustomerById(@Context HttpServletRequest request) {
		Customer customer = CustomerState.getCustomer(request);
		if (customer != null) {
			CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
			wrapper.wrapDetails(customer, request);
			return wrapper;
		}
		throw BroadleafWebServicesException.build(Response.Status.BAD_REQUEST.getStatusCode())
				.addMessage(BroadleafWebServicesException.CUSTOMER_NOT_FOUND);

	}

	@POST
	@Path("register")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerWrapper registerCustomer(@Context HttpServletRequest request, @FormParam("username") String username,
			@FormParam("password") String password) {
		if (null != customerService.readCustomerByUsername(username, false)) {
			throw BroadleafWebServicesException.build(Response.Status.CONFLICT.getStatusCode())
					.addMessage(USERNAME_EXISTED);
		}
		Customer customer = customerService.createNewCustomer();
		customer.setUsername(username);
		customer.setUnencodedPassword(password);
		customer.setEmailAddress(username);
		CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
		wrapper.wrapDetails(customer, request);
		customerService.registerCustomer(customer, password, password);
		return wrapper;
	}

	@POST
	@Path("login")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerWrapper loginCustomer(@Context HttpServletRequest request, @FormParam("username") String username,
			@FormParam("password") String password) {
		Customer customer = customerService.readCustomerByUsername(username, false);
		boolean bool = false;
		if (null != customer) {
			bool = customerService.isPasswordValid(password, customer.getPassword(), customer);
		} else {
			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(USERNAME_NOT_EXISTED);
		}
		if (!bool) {
			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(PASSWORD_ERROR);
		}
		customer.setUnencodedPassword(password);
		blLoginService.loginCustomer(customer);
		List<FSThirdPartyCustomer> thirdPartyCustomers = ((FSCustomerService) customerService)
				.getThirdPartyCustomer(customer);
		CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
		wrapper.wrapDetails(customer, request);
		wrapper.wrapThirdAccount(thirdPartyCustomers);
		return wrapper;
	}

	@POST
	@Path("changePassword")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerWrapper changePassword(@Context HttpServletRequest request,
			@FormParam("currentPasswrod") String currentPasswrod, @FormParam("newPassword") String password) {
		Customer customer = CustomerState.getCustomer(request);

		if (customer != null) {
			if (!customerService.isPasswordValid(currentPasswrod, customer.getPassword(), customer)) {
				throw BroadleafWebServicesException.build(Response.Status.NOT_ACCEPTABLE.getStatusCode())
						.addMessage(CURRENT_PASSWORD_ERROR);
			}

			PasswordChange passwordChange = new PasswordChange(customer.getUsername());
			passwordChange.setNewPassword(password);
			passwordChange.setPasswordChangeRequired(true);
			passwordChange.setEmail(customer.getEmailAddress());
			passwordChange.setSendResetEmailReliableAsync(true);

			customer = customerService.changePassword(passwordChange);
			CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
			wrapper.wrapDetails(customer, request);
			return wrapper;
		}

		throw BroadleafWebServicesException.build(Response.Status.BAD_REQUEST.getStatusCode())
				.addMessage(BroadleafWebServicesException.CUSTOMER_NOT_FOUND);

	}

	@GET
	@Path("address")
	public List<CustomerAddressWrapper> findAddressByCustomer(@Context HttpServletRequest request) {
		Customer customer = CustomerState.getCustomer(request);
		if (customer != null) {
			List<CustomerAddress> activeCustomerAddresses = blCustomerAddressService
					.readActiveCustomerAddressesByCustomerId(customer.getId());

			if (activeCustomerAddresses != null && !activeCustomerAddresses.isEmpty()) {
				List<CustomerAddressWrapper> wrappers = new ArrayList<CustomerAddressWrapper>();

				for (CustomerAddress activeCustomerAddress : activeCustomerAddresses) {
					CustomerAddressWrapper wrapper = (CustomerAddressWrapper) context
							.getBean("fsCustomerAddressWrapper");
					wrapper.wrapDetails(activeCustomerAddress, request);
					wrappers.add(wrapper);
				}
				return wrappers;
			}

			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(ADDRESS_NOT_FOUND);
		}
		throw BroadleafWebServicesException.build(Response.Status.BAD_REQUEST.getStatusCode())
				.addMessage(BroadleafWebServicesException.CUSTOMER_NOT_FOUND);

	}

	/**
	 * 保存地址
	 */
	@POST
	@Path("address/saveAddress")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerAddressWrapper saveAddress(@Context HttpServletRequest request,
			@FormParam("receiverName") String receiverName, @FormParam("receiverPhone") String receiverPhone,
			@FormParam("addressCountry") String addressCountry, @FormParam("addressProvince") String addressProvince,
			@FormParam("addressCity") String addressCity, @FormParam("poscalCode") String poscal,
			@FormParam("addressDetail") String addressDetail) throws ServiceException {

		Customer customer = CustomerState.getCustomer(request);

		// CustomerAddressForm form = new CustomerAddressForm();

		Address addr = blAddressService.create();
		addr.setFirstName(receiverName);
		addr.setCity(addressCity);
		addr.setAddressLine1(addressDetail);

		State state = blStateService.findStateByAbbreviation(addressProvince);
		addr.setState(state);

		Country country = blCountryService.findCountryByAbbreviation(addressCountry);
		addr.setCountry(country);

		Phone phone = blPhoneService.create();
		phone.setPhoneNumber(receiverPhone);
		phone.setActive(true);
		addr.setPhonePrimary(phone);
		addr.setDefault(true);
		addr.setPostalCode(poscal);

		// form.setAddress(address);

		Address address = blAddressService.saveAddress(addr);
		CustomerAddress customeAddr = blCustomerAddressService.create();
		customeAddr.setCustomer(customer);
		customeAddr.setAddress(address);

		CustomerAddress customerAddress = blCustomerAddressService.saveCustomerAddress(customeAddr);
		if (address.isDefault()) {
			blCustomerAddressService.makeCustomerAddressDefault(customerAddress.getId(),
					customerAddress.getCustomer().getId());
		}
		CustomerAddress activeCustomerAddress = blCustomerAddressService.findDefaultCustomerAddress(customer.getId());
		CustomerAddressWrapper wrapper = (CustomerAddressWrapper) context.getBean("fsCustomerAddressWrapper");

		wrapper.wrapDetails(activeCustomerAddress, request);
		return wrapper;

	}

	/**
	 * 移除地址
	 */
	@DELETE
	@Path("address/delete/{addressId}")
	@Consumes("application/x-www-form-urlencoded")
	public List<CustomerAddressWrapper> deleteAddress(@Context HttpServletRequest request,
			@PathParam("addressId") Long addressId) throws ServiceException {

		Customer customer = CustomerState.getCustomer(request);

		// ManageCustomerAddressesController controller = new
		// ManageCustomerAddressesController();
		// Model model = null;
		// BindingResult result = null;
		// RedirectAttributes redirectAttributes = null;
		// String response = controller.removeCustomerAddress(request, model,
		// addressId,redirectAttributes);
		// return response;
		try {
			blCustomerAddressService.deleteCustomerAddressById(addressId);
		} catch (DataIntegrityViolationException e) {
			throw BroadleafWebServicesException.build(Response.Status.NOT_ACCEPTABLE.getStatusCode())
					.addMessage(ADDRESS_IN_ACTIVE_CART);
		}

		// 移除成功，返回当前客户地址列表
		List<CustomerAddress> activeCustomerAddresses = blCustomerAddressService
				.readActiveCustomerAddressesByCustomerId(customer.getId());
		List<CustomerAddressWrapper> wrappers = new ArrayList<CustomerAddressWrapper>();
		if (activeCustomerAddresses != null && !activeCustomerAddresses.isEmpty()) {

			for (CustomerAddress activeCustomerAddress : activeCustomerAddresses) {
				CustomerAddressWrapper wrapper = (CustomerAddressWrapper) context.getBean("fsCustomerAddressWrapper");
				wrapper.wrapDetails(activeCustomerAddress, request);
				wrappers.add(wrapper);
			}
		}
		return wrappers;
	}

	/**
	 * 查询customerAddress
	 */
	@GET
	@Path("address/{addressId}")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerAddressWrapper findCustomerAddressById(@Context HttpServletRequest request,
			@PathParam("addressId") Long addressId) throws ServiceException {

		CustomerAddress customerAddress = blCustomerAddressService.readCustomerAddressById(addressId);

		CustomerAddressWrapper wrapper = (CustomerAddressWrapper) context.getBean("fsCustomerAddressWrapper");
		wrapper.wrapDetails(customerAddress, request);

		return wrapper;
	}

	/**
	 * 查询默认地址
	 */
	@GET
	@Path("address/default")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerAddressWrapper findDefaultCustomerAddress(@Context HttpServletRequest request)
			throws ServiceException {

		Customer customer = CustomerState.getCustomer(request);
		Long customerId = customer.getId();
		CustomerAddress customerAddress = blCustomerAddressService.findDefaultCustomerAddress(customerId);

		CustomerAddressWrapper wrapper = (CustomerAddressWrapper) context.getBean("fsCustomerAddressWrapper");
		wrapper.wrapDetails(customerAddress, request);

		return wrapper;
	}

	/**
	 * 更改地址信息
	 */
	@POST
	@Path("address/updateAddress/{addressId}")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerAddressWrapper updateCustomerAddressById(@Context HttpServletRequest request,
			@PathParam("addressId") Long addressId, @FormParam("receiverName") String receiverName,
			@FormParam("receiverPhone") String receiverPhone, @FormParam("addressCountry") String addressCountry,
			@FormParam("addressProvince") String addressProvince, @FormParam("addressCity") String addressCity,
			@FormParam("poscalCode") String poscal, @FormParam("addressDetail") String addressDetail,
			@FormParam("isDefault") String isDefault) throws ServiceException {

		Customer customer = CustomerState.getCustomer(request);

		CustomerAddress customerAddress = blCustomerAddressService.readCustomerAddressById(addressId);
		if (customerAddress == null) {
			throw new IllegalArgumentException("Customer Address not found with the specified customerAddressId");
		}

		Address address = customerAddress.getAddress();
		State state = address.getState();
		Phone phone = address.getPhonePrimary();

		address.setFirstName(receiverName);
		phone.setPhoneNumber(receiverPhone);
		state.setAbbreviation(addressProvince);
		address.setCity(addressCity);
		address.setPostalCode(poscal);
		address.setAddressLine1(addressDetail);
		if (isDefault.equalsIgnoreCase("true")) {
			address.setDefault(true);
		} else {
			address.setDefault(false);
		}
		address.setState(state);
		address.setPhonePrimary(phone);

		Address addr = blAddressService.saveAddress(address);

		customerAddress.setAddress(addr);

		CustomerAddress customerAddr = blCustomerAddressService.saveCustomerAddress(customerAddress);
		if (addr.isDefault()) {
			blCustomerAddressService.makeCustomerAddressDefault(addressId, customer.getId());
		}

		CustomerAddressWrapper wrapper = (CustomerAddressWrapper) context.getBean("fsCustomerAddressWrapper");
		wrapper.wrapDetails(customerAddr, request);

		return wrapper;

	}

	/**
	 * 验证手机号码/邮箱确实存在 应用场景：忘记密码第一步，填写手机号码/邮箱
	 */
	@POST
	@Path("resetPassword/sendVarify")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerWrapper sendVarify(@Context HttpServletRequest request, @FormParam("account") String username,
			@FormParam("uuid") String s, @FormParam("cacheable") @DefaultValue("true") boolean cacheable) {
		Customer customer = customerService.readCustomerByUsername(username, cacheable);
		boolean b;
		if (null == customer) {
			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(USERNAME_NOT_EXISTED);
		} else {
			if (username.contains("@")) {
				// 发送邮件
				LoginController controller = new LoginController();
				customerService.sendForgotPasswordNotification(username, controller.getResetPasswordUrl(request));
				// GenericResponse errorResponse =
				// customerService.sendForgotPasswordNotification(username,
				// getResetPasswordUrl(request));
				b = true;
			} else {
				// 发送验证码到手机，username
				String ret = captchaService.getNumberCodeForID(s, username);
				if (ret != null && !ret.isEmpty()) {
					b = true;
				} else {
					b = false;
				}
			}

		}
		if (b) {
			CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
			wrapper.wrapDetails(customer, request);
			return wrapper;
		} else {
			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(SEND_VARIFY_ERROR);
		}
	}

	/**
	 * 验证验证码，重置密码 应用场景：忘记密码第二步，
	 */
	@POST
	@Path("resetPassword")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerWrapper resetPasswordByVarify(@Context HttpServletRequest request, @FormParam("uuid") String uuid,
			@FormParam("varify") String varify, @FormParam("phoneNumber") String phoneNumber,
			@FormParam("newPassword") String newPassword) {
		// Customer customer =
		// customerService.readCustomerByUsername(username,cacheable);
		boolean b = captchaService.validateResponseForID(uuid, varify, 0);
		if (b) {
			// 验证码正确则changePassword

			Customer customer = customerService.readCustomerByUsername(phoneNumber, true);

			PasswordReset passwordReset = new PasswordReset();
			passwordReset.setPasswordChangeRequired(true);
			passwordReset.setPasswordLength(newPassword.length());
			passwordReset.setUsername(customer.getUsername());
			passwordReset.setEmail(customer.getEmailAddress());
			passwordReset.setSendResetEmailReliableAsync(true);

			customer = customerService.resetPassword(passwordReset);
			CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
			wrapper.wrapDetails(customer, request);
			return wrapper;

		} else if (!b) {
			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(VARIFY_ERROR);
		} else {
			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(UNKNOWN_ERROR);
		}
	}

	@GET
	@Path("uid")
	public CustomerWrapper getCustomerByUid(@Context HttpServletRequest request, @QueryParam("openId") String uid,
			@QueryParam("unionId") @DefaultValue("") String unionId) {
		// Customer customer = fscustomer3thService.getCustomerByUid(uid);
		Customer customer = null;
		if (!org.springframework.util.StringUtils.isEmpty(unionId))
			customer = fscustomer3thService.getCustomer3thByUnionid(unionId);
		else
			customer = fscustomer3thService.getCustomerByUid(uid);
		if (null == customer) {
			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(BroadleafWebServicesException.CUSTOMER_NOT_FOUND);
		}

		CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
		List<FSThirdPartyCustomer> thirdPartyCustomers = ((FSCustomerService) customerService)
				.getThirdPartyCustomer(customer);
		wrapper.wrapDetails(customer, request);
		wrapper.wrapThirdAccount(thirdPartyCustomers);
		return wrapper;
	}

	/**
	 * 供资讯调用，提供绑定openId的第三方帐户到username（邮箱）帐户的绑定，不需要通知资讯进行绑定
	 * 
	 * @param request
	 * @param channelId
	 * @param uid
	 * @param username
	 * @param password
	 * @param isLogin
	 * @return
	 */
	@POST
	@Path("bind")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerWrapper bindAccount(@Context HttpServletRequest request, @FormParam("channelId") String channelId,
			@FormParam("openId") String uid, @FormParam("username") String username,
			@FormParam("password") String password, @DefaultValue("false") @FormParam("isLogin") boolean isLogin,
			@FormParam("unionId") @DefaultValue("") String unionId,
			@FormParam("avatar") @DefaultValue("") String avatar,
			@FormParam("nickname") @DefaultValue("") String nickname) {
		Customer customer = customerService.readCustomerByUsername(username, true);
		if (null == customer) {
			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(BroadleafWebServicesException.CUSTOMER_NOT_FOUND);
		}
		Long ID = customer.getId();
		boolean result = false;
		CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
		try {
			// TODO: 根据uid查询unionId
			result = fscustomer3thService.bindAccount(channelId, uid, ID, password, isLogin, unionId, null, null);
			wrapper.wrapBindResult(customer, request, result);
		} catch (ThirdAccountBindedException e) {
			e.printStackTrace();
			wrapper.wrapBindResult(customer, request, result, -1);
		} catch (ThirdAccountBindToMultipleAccountException e) {
			e.printStackTrace();
			wrapper.wrapBindResult(customer, request, result, -2);
		} catch (AccountBindedThirdAccountException e) {
			e.printStackTrace();
			wrapper.wrapBindResult(customer, request, result, -3);
		}

		return wrapper;
	}

	@POST
	@Path("TVphone")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerWrapper TVLoginByPhone(@Context HttpServletRequest request,
			@FormParam("phoneNumber") String phoneNumber, @FormParam("verify") String verify,
			@FormParam("uuid") String uuid) {

		FSCustomer customer = (FSCustomer) customerService.readCustomerByUsername(phoneNumber, true);
		if (customer == null) {
			// create account by phone number and device ID(uuid)
			customer = loginServer3th.register3thCustomer(phoneNumber, uuid, CHANNEL.DEVICE_ID.toString(), null, null);
			customer.setVerified(true);
			blLoginService.loginCustomer(customer);
		} else {
			if (!fscustomer3thService.checkCustomerBy3thUid(uuid)) {
				FSThirdPartyCustomer fscustomer3th = fscustomer3thService.create3thCustomerByUid(uuid);
				fscustomer3th.setCustomer(customer);
				fscustomer3thService.save(fscustomer3th);
			} else { // device ID may bind to another phone.
				FSThirdPartyCustomer fscustomer3th = fscustomer3thService.getCustomer3thByUid(uuid);
				fscustomer3th.setCustomer(customer);
				fscustomer3thService.save(fscustomer3th);
			}
			loginServer3th.loginDirectly(customer);
		}
		CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
		wrapper.wrapDetails(customer, request);
		return wrapper;

	}

	@GET
	@Path("TVuuid")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerWrapper TVLoginByUUID(@Context HttpServletRequest request, @QueryParam("uuid") String uuid) {

		FSCustomer customer = fscustomer3thService.getCustomerByUid(uuid);
		if (customer != null) {
			loginServer3th.loginDirectly(customer);

			CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
			wrapper.wrapDetails(customer, request);
			return wrapper;
		}

		throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
				.addMessage(BroadleafWebServicesException.CUSTOMER_NOT_FOUND);
	}

	/**
	 * TV端用户购买产品 填写手机号码
	 */
	@POST
	@Path("TV/sendVerify")
	@Consumes("application/x-www-form-urlencoded")
	public ResultWrapper TVsendVarify(@Context HttpServletRequest request, @FormParam("account") String mobile,
			@FormParam("uuid") String uuid, @QueryParam("cacheable") @DefaultValue("true") boolean cacheable) {

		boolean b;
		// 发送验证码到手机，username
		String ret = captchaService.getNumberCodeForID(uuid, mobile);
		if (ret != null && !ret.isEmpty()) {
			b = true;
		} else {
			b = false;
		}
		if (b) {
			ResultWrapper wrapper = (ResultWrapper) context.getBean("fsResultWrapper");
			wrapper.wrapDetails(SEND_VARIFY_SUCCESS);
			return wrapper;
		} else {
			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(SEND_VARIFY_ERROR);
		}
	}

	/**
	 * TV端验证码
	 */
	// @POST
	// @Path("TV/validationCode")
	// @Consumes("application/x-www-form-urlencoded")
	// public CustomerWrapper validationCode(@Context HttpServletRequest
	// request, @FormParam("uuid")String uuid,
	// @FormParam("verify")String varify,@FormParam("phoneNumber")String
	// phoneNumber){
	//// Customer customer =
	// customerService.readCustomerByUsername(username,cacheable);
	// boolean b = captchaService.validateResponseForID(uuid,varify,0);
	// if(b){
	// //验证码正确则创建用户
	//
	// Customer customer =
	// customerService.readCustomerByUsername(phoneNumber,true);
	// if(customer == null){
	// // create account by phone number
	// customer = customerService.createCustomer();
	// customer.setId(customerService.findNextCustomerId());
	// customer.setFirstName(phoneNumber);
	// customer.setUsername(phoneNumber);
	// ((FSCustomerImpl)customer).setMobile(phoneNumber);
	// String password = phoneNumber;
	// ((FSCustomerImpl)customer).setVerified(true);
	// ((FSCustomerService)
	// customerService).easyRegisterCustomer(customer,password);
	//// blLoginService.loginCustomer(customer);
	// }
	// else{
	//// loginServer3th.loginDirectly(customer);
	// }
	// CustomerWrapper wrapper = (CustomerWrapper)
	// context.getBean("fsCustomerWrapper");
	// wrapper.wrapDetails(customer, request);
	// return wrapper;
	// }throw
	// BroadleafWebServicesException.build(Response.Status.NOT_ACCEPTABLE.getStatusCode())
	// .addMessage(VERIFY_CODE_ERROR);
	// }

	/**
	 * 创建二维码图片url
	 * 
	 * @param request
	 * @param phoneNumber
	 * @param verify
	 * @param uuid
	 * @param pid
	 * @param quantity
	 * @return
	 */
	@POST
	@Path("TV/validationCode")
	@Consumes("application/x-www-form-urlencoded")
	public ResultWrapper TVcreate2DimensionCode(@Context HttpServletRequest request, @Context UriInfo uriInfo,
			@FormParam("phoneNumber") String phoneNumber, @FormParam("verify") String verify,
			@FormParam("uuid") String uuid, @FormParam("productId") Long pid, @FormParam("categoryId") Long cid,
			@FormParam("quantity") Integer quantity) {

		// 1： 验证 手机验证码
		boolean b = captchaService.validateResponseForID(uuid, verify, 0);
		b = true;
		if (b) {
			// 2: Load customer
			FSCustomer customer = loginServer3th.getPhoneUUIDCustomer(phoneNumber, uuid);

			// 3: Add product to cart

			Order cart = orderService.findCartForCustomer(customer);
			if (cart == null) {
				cart = orderService.createNewCartForCustomer(customer);
				CartState.setCart(cart);
			}

			try {
				// We allow product options to be submitted via form post or via
				// query params. We need to take
				// the product options and build a map with them...
				HashMap<String, String> productOptions = getOptions(uriInfo);

				OrderItemRequestDTO orderItemRequestDTO = new OrderItemRequestDTO();
				orderItemRequestDTO.setProductId(pid);
				orderItemRequestDTO.setCategoryId(cid);
				orderItemRequestDTO.setQuantity(quantity);

				// If we have product options set them on the DTO
				if (productOptions.size() > 0) {
					orderItemRequestDTO.setItemAttributes(productOptions);
				}

				Order order = orderService.addItem(cart.getId(), orderItemRequestDTO, true);
				order = orderService.save(order, true);

			} catch (PricingException e) {
				throw BroadleafWebServicesException.build(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), null,
						null, e);
			} catch (AddToCartException e) {
				throw BroadleafWebServicesException.build(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), null,
						null, e);
			}

			// 4: create md5 by customerId + productId + currentTime, 并保存Map映射。
			String md5 = loginServer3th.getMD5byTVOrderInfo(customer.getId(), pid);
			FSAssistant assistant = assistantService.create(md5);
			assistant.setCustomer(customer);
			assistantService.save(assistant);

			// 5: create redirect URL
			String resultURL = HOST + request.getContextPath() + URI_POSTFIX + md5;

			ResultWrapper wrapper = (ResultWrapper) context.getBean("fsResultWrapper");
			wrapper.wrapDetails(resultURL);
			return wrapper;
		}
		throw BroadleafWebServicesException.build(Response.Status.NOT_ACCEPTABLE.getStatusCode())
				.addMessage(VERIFY_CODE_ERROR);

	}

	protected HashMap<String, String> getOptions(UriInfo uriInfo) {
		MultivaluedMap<String, String> multiValuedMap = uriInfo.getQueryParameters();
		HashMap<String, String> productOptions = new HashMap<String, String>();

		// Fill up a map of key values that will represent product options
		Set<String> keySet = multiValuedMap.keySet();
		for (String key : keySet) {
			if (multiValuedMap.getFirst(key) != null) {
				// Product options should be returned with "productOption." as a
				// prefix. We'll look for those, and
				// remove the prefix.
				if (key.startsWith("productOption.")) {
					productOptions.put(StringUtils.removeStart(key, "productOption."), multiValuedMap.getFirst(key));
				}
			}
		}
		return productOptions;
	}

	// provide user info to 3rd party App
	@GET
	@Path("grab/{username}")
	public CustomerWrapper grabCustomerInfo(@Context HttpServletRequest request,
			@PathParam("username") String username) {
		Customer customer = customerService.readCustomerByUsername(username, false);
		if (null == customer) {
			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(USERNAME_NOT_EXISTED);
		}
		CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
		wrapper.wrapDetails(customer, request);
		return wrapper;
	}

	@POST
	@Path("register/login")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerWrapper registerThenLogin(@Context HttpServletRequest request,
			@FormParam("username") String username, @FormParam("uid") String uid,
			@FormParam("channelId") String channelId, @FormParam("avatar") @DefaultValue("") String avatar,
			@FormParam("unionId") @DefaultValue("") String unionId) {
		Customer customer = loginServer3th.register3thCustomer(username, uid, channelId, avatar, unionId);
		if (null != customer) {
			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(USERNAME_NOT_EXISTED);
		}

		loginServer3th.loginDirectly(customer);
		CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
		wrapper.wrapDetails(customer, request);
		return wrapper;
	}

	/**
	 * 第三方用户注册Endpoint，若用户存在，直接返回用户信息
	 * 
	 * @param request
	 * @param channelId
	 * @param uid
	 * @param username
	 * @return
	 */
	@POST
	@Path("register/thirdAccount")
	@Consumes("application/x-www-form-urlencoded")
	public CustomerWrapper registerThirdAccount(@Context HttpServletRequest request,
			@FormParam("channelId") String channelId, @FormParam("uid") String uid, @FormParam("name") String username,
			@FormParam("avatar") String avatar, @FormParam("unionId") String unionId) {

		FSCustomer customer = this.fscustomer3thService.getCustomerByUid(uid);
		if (customer == null && !org.springframework.util.StringUtils.isEmpty(unionId)) {
			customer = this.fscustomer3thService.getCustomer3thByUnionid(unionId);
		}

		if (null == customer) {
			customer = thirdPartyLoginServer.register3thCustomer(username, uid, channelId, avatar, unionId);
		}
		if (org.springframework.util.StringUtils.isEmpty(customer.getFirstName())) {
			customer.setFirstName(username);
			this.customerService.saveCustomer(customer);
		}
		loginServer3th.loginDirectly(customer);
		CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
		wrapper.wrapDetails(customer, request);
		return wrapper;
	}

	/**
	 * 查询第三方用户id是否存在，如果存在，直接返回用户信息 和{@link CustomerEndpoint#getCustomerByUid}
	 * 一样功能
	 * 
	 * @param request
	 * @param channelId
	 *            暂不使用，xinying确认不同渠道用户id格式不同
	 * @param uid
	 * @return
	 */
	@GET
	@Path("grab/thirdAccount")
	public CustomerWrapper findThirdAccountInfo(@Context HttpServletRequest request,
			@QueryParam("channelId") String channelId, @QueryParam("uid") String uid) {
		FSCustomer customer = this.fscustomer3thService.getCustomerByUid(uid);
		if (null == customer) {
			throw BroadleafWebServicesException.build(Response.Status.NOT_FOUND.getStatusCode())
					.addMessage(USERNAME_NOT_EXISTED);
		}
		CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
		wrapper.wrapDetails(customer, request);
		return wrapper;
	}

	@GET
	@Path("merge")
	public MergeCustomerWrapper merge(@Context HttpServletRequest request, @QueryParam("channelId") String channelId,
			@QueryParam("openId") String openId, @QueryParam("customerId") long customerId) {
		FSCustomer to = (FSCustomer) this.customerService.readCustomerById(customerId);
		FSCustomer from = this.fscustomer3thService.getCustomerByUid(openId);

		MergeCustomerWrapper wrapper = (MergeCustomerWrapper) context.getBean("fsMergeCustomerWrapper");
		if (to == null) {
			// 指定的合并账号不存在
			wrapper.wrapBindMergedCustomer(null, request, -1);
		} else if (from == null) {
			// 第三方被合并账号不存在
			wrapper.wrapBindMergedCustomer(null, request, -2);
		} else {
			try {
				List<FSThirdPartyCustomer> thirdAccountList = this.fscustomer3thService
						.readThirdPartyCustomerForCustomer(to);
				boolean isBindAccountOfChannel = false;
				for (FSThirdPartyCustomer thirdAccount : thirdAccountList) {
					if (thirdAccount.getChannelId().equals(channelId)) {
						isBindAccountOfChannel = true;
						break;
					}
				}
				if (from.isBindedToEmail()) {
					// 第三方账号已绑定邮箱
					wrapper.wrapBindMergedCustomer(null, request, -4);
				} else if (isBindAccountOfChannel) {
					// 指定的绑定账号已绑定第三方账号
					wrapper.wrapBindMergedCustomer(null, request, -5);
				} else {
					((FSCustomerService) this.customerService).mergeCustomers(from, to);
					wrapper.wrapBindMergedCustomer(to, request, 0);
				}
			} catch (PricingException e) {
				e.printStackTrace();
				wrapper.wrapBindMergedCustomer(null, request, -3);
			}
		}
		return wrapper;
	}

	@GET
	@Path("findById")
	public CustomerWrapper findCustomerById(@Context HttpServletRequest request,
			@QueryParam("customerId") Long customerId) {
		Customer customer = this.customerService.readCustomerById(customerId);

		if (customer != null) {
			CustomerWrapper wrapper = (CustomerWrapper) context.getBean("fsCustomerWrapper");
			List<FSThirdPartyCustomer> thirdPartyCustomers = ((FSCustomerService) customerService)
					.getThirdPartyCustomer(customer);
			wrapper.wrapDetails(customer, request);
			wrapper.wrapThirdAccount(thirdPartyCustomers);
			return wrapper;
		}
		throw BroadleafWebServicesException.build(Response.Status.BAD_REQUEST.getStatusCode())
				.addMessage(BroadleafWebServicesException.CUSTOMER_NOT_FOUND);

	}
}
